from graphviz import Digraph
import uuid
from random import sample
# from SemanticMatch.sim import Simer
# from SemanticMatch.nlu import NLUER

class Node(object):
    """节点类"""
    def __init__(self, intent=None, intent_text=None,accept=None, refuse=None, lchild=None, rchild=None):
        '''

        :param intent: 意图
        :param intent_text: 意图话术
        :param accept: 客户回话接受同意语句
        :param refuse: 客户回话拒绝语句
        :param lchild: 左子树
        :param rchild: 右子树
        '''
        self.intent = intent
        self.intent_text= intent_text
        self.accept = accept
        self.refuse = refuse
        self.lchild = lchild
        self.rchild = rchild

    def __str__(self):
        return "意图是：%s" % (self.intent)
    """树类"""
class Tree(object):
    def __init__(self, root=None, region =None):
        '''

        :param root:
        :param region:
        '''
        self.root = root
        self.region = region
        self.dot = Digraph(comment='Binary Tree')

    def add(self, item):
        if item is not None:
            node = Node(item['intent'], item['intent_text'], item['accept'], item['refuse'])  # 将Node类实例化参数node
        else:
            node =Node()
        if self.root is None:
            self.root = node
            return
        queue = [self.root]  # 创建一个队列，将根节点放入队列中
        while queue:
            cur_node = queue.pop(0)  # 向队列queue中取出第一个节点进行判断
            if cur_node.lchild is None:
                cur_node.lchild = node
                return
            else:
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                cur_node.rchild = node
                return
            else:
                queue.append(cur_node.rchild)
    def  breadth(self):

        if self.root is None:  #首先判断根节点是否为空，为空则返回
            return
        queue=[self.root]#将根节点放入队列中
        while queue:
            cur_node = queue.pop(0)#取出节点
            print(cur_node.intent,end=' ')#打印节点值，也是广度遍历的值
            if cur_node.lchild is not None:#判断左子树
                queue.append(cur_node.lchild)
            if cur_node.rchild is not None:#判断右子树
                queue.append(cur_node.rchild)
    """先序遍历"""
    def preorder(self,root):
        if root ==None:
            return
        print(root.intent,end=',')
        self.preorder(root.lchild)
        self.preorder(root.rchild)
    """中序遍历"""
    def inorder(self, root):
        if not root :
            return None
        self.inorder(root.lchild)
        print(root.intent, end=',')
        self.inorder(root.rchild)


  # 利用Graphviz实现二叉树的可视化
    def print_tree(self, save_path='./Binary_Tree.gv', label=False):

        # colors for labels of nodes
        colors = ['skyblue', 'tomato', 'orange', 'purple', 'green', 'yellow', 'pink', 'red']

        # 绘制以某个节点为根节点的二叉树
        def print_node(node, node_tag):
            # 节点颜色
            color = sample(colors,1)[0]
            if node.lchild is not None:
                lchild_tag = str(node.lchild.intent)            # 左节点的数据
                lchild_tag_text = str(node.lchild.intent_text)            # 左节点的数据
                lchild_lable = str(uuid.uuid1())
                self.dot.node(lchild_lable, label=lchild_tag, style='filled', color=color, fontname='SimSun' )    # 左节点
                label_string = 'yes' if label else ''    # 是否在连接线上写上标签，表明为左子树
                print_node(node.lchild, lchild_lable)
                self.dot.edge(node_tag, lchild_lable, label=label_string)  # 左节点与其父节点的连线
            else:
                return
            if node.rchild is not None:
                rchild_tag = str(node.rchild.intent)
                rchild_tag_text = str(node.rchild.intent_text)
                rchild_lable = str(uuid.uuid1())
                self.dot.node(rchild_lable,label= rchild_tag, style='filled', color=color,fontname='SimSun')
                label_string = 'No' if label else ''  # 是否在连接线上写上标签，表明为右子树
                print_node(node.rchild, rchild_lable)
                self.dot.edge(node_tag, rchild_lable, label=label_string)
            else:
                return
        # 如果树非空
        if self.root is not None:
            root_tag = str(self.root.intent)                # 根节点标签
            self.dot.node(root_tag, str(self.root.intent), style='filled', color=sample(colors,1)[0], fontname='SimSun')     # 创建根节点
            print_node(self.root, root_tag)
        self.dot.view()
        self.dot.render(save_path)                              # 保存文件为指定文件


    #
    # """任务树会话"""
    # def start(self):
    #     index=self.root
    #     while index is not None:
    #         response_text="好的"
    #         """语义匹配策略"""
    #         nlu2=NLUER(response_text)
    #         accept_len=len(index.accept)
    #         refuse_len = len(index.refuse)
    #         res =index.accept+index.refuse
    #         for i in range(accept_len+refuse_len):
    #             nlu1 = NLUER(res[i])
    #             sim = Simer(nlu1,nlu2)
    #             pre_val=sim.sim_by_sentence_vec
    #             if pre_val >=0.8 and i<accept_len:
    #                 smc_index =index.lchild
    #                 break
    #             elif pre_val >=0.8 and accept_len<=i<accept_len+refuse_len:
    #                 smc_index = index.rchild
    #                 break
    #             if i == accept_len+refuse_len-1:
    #                 smc_index = None#万能节点
    #             else:
    #                 continue
    #         semanticMc_value = pre_val
    #         """倾向性判断celue"""
    #         index =smc_index
    #     if semanticMc_value >0.8:
    #         return 'success'
    #     else:
    #         return 'dsfault'


if __name__== '__main__':
    tree=Tree()
    list = [
        {'intent': '确认身份', 'intent_text': '您好！您是王先生嘛', 'accept': ['是', '嗯'], 'refuse': ['不是', '不对']},
        {'intent': '有无症状', 'intent_text': '您哪里痛', 'accept': ['痛', '不舒服'], 'refuse': ['不痛', '没事']},
        {'intent': '认错人', 'intent_text': '不好意思打扰您啦', 'accept': ['再见'], 'refuse': ['不是']},
        {'intent': '是否检查', 'intent_text': '您去检查过吗', 'accept': ['去过', '看过'], 'refuse': ['没去过', '不想']},
        {'intent': '健康管理', 'intent_text': '您需要身体健康管理计划，啊', 'accept': ['好的'], 'refuse': ['不']},
        None,
        None,
        {'intent': '检查情况', 'intent_text': '医生说什么', 'accept': ['医生说挺好'], 'refuse': ['医生说需要继续观察']},
        {'intent': '劝导检查', 'intent_text': '您还是去医院看看吧', 'accept': ['好的', '会去'], 'refuse': ['不拉']},
        None,
        None,
        None,
        None,
        None,
        None,
        {'intent': '祝福', 'intent_text': '祝您生活愉快', 'accept': ['好的', '会去'], 'refuse': ['好的']},
        # {'有无症状','您哪里痛',{'痛','不舒服'},{'不痛','没事'}},
        # {'认错人', '不好意思打扰您啦',{'再见'}{'不是'}},
        # {'是否检查','您去检查过吗',{'去过','看过'},{'没去过','不想'}},
        # {'劝导检查','您还是最近去医院一趟吧',{'好的','过几天'}{'不去'}},
    ]
    for item in list:
        tree.add(item)
    tree.breadth()
    print('\n')
    root = tree.root
    tree.preorder(root)
    print('\n')
    tree.inorder(root)
    tree.print_tree(save_path='./BTree.gv', label=True)
    # print(tree.start())